package com.ildepinc.persistence.concretes;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;

import com.ildepinc.persistence.abstracts.DaoTableGenericExpirable;
import com.ildepinc.persistence.concretes.daos.DaoLocale;
import com.ildepinc.persistence.concretes.models.Locale;

@TestMethodOrder(OrderAnnotation.class)
class DaoLocaleTest {

  private static Persistence persistenceLayer;
  private DaoLocale daoLocale;
  private Timestamp currentTimestamp = new Timestamp(System.currentTimeMillis());
  private Timestamp validToDefault = Utils.addDaysToTimestamp(currentTimestamp, 365);

  @BeforeAll
  static void setUpBeforeClass() throws Exception {
    persistenceLayer = new Persistence();
  }

  @Test
  @Order(1)
  void testStartLayer() {
    assertTrue(persistenceLayer.startLayer());
  }

  @Test
  @Order(2)
  void testManualDeleteTableGenericExpirable() {
    this.daoLocale = (DaoLocale) persistenceLayer.getDaoTableGenericExpirableMap().get("DaoLocale");
    assertTrue(this.daoLocale instanceof DaoTableGenericExpirable);
    String deleteSql = this.daoLocale.getTable().getSqlDelete();
    this.daoLocale.setSqlCommand(deleteSql);
    ArrayList<Object> sqlParameters = new ArrayList<Object>();
    sqlParameters.add(2L);
    sqlParameters.add(2L);
    this.daoLocale.setSqlParameters(sqlParameters);
    Integer rowsAffected = 0;
    try {
      rowsAffected = this.daoLocale.doManualDmlOrDdl();
    } catch (Exception e) {
      e.printStackTrace();
    }
    assertTrue((rowsAffected == 0) || (rowsAffected == 1));
  }

  @Test
  @Order(3)
  void testDeleteTableGenericExpirable() {
    this.daoLocale = (DaoLocale) persistenceLayer.getDaoTableGenericExpirableMap().get("DaoLocale");
    assertTrue(this.daoLocale instanceof DaoTableGenericExpirable);
    Integer rowsAffected = null;
    HashMap<String, Object> primaryKeys = new HashMap<String, Object>();
    primaryKeys.put("LANGUAGE_ID", 1L);
    primaryKeys.put("COUNTRY_ID", 1L);
    try {
      rowsAffected = this.daoLocale.doDelete(primaryKeys);
    } catch (Exception e) {
      e.printStackTrace();
    }
    assertTrue((rowsAffected == 0) || (rowsAffected == 1));
  }

  @Test
  @Order(4)
  void testInsertTableGenericExpirable() {
    this.daoLocale = (DaoLocale) persistenceLayer.getDaoTableGenericExpirableMap().get("DaoLocale");
    assertTrue(this.daoLocale instanceof DaoTableGenericExpirable);
    Integer rowsAffected = null;
    // Locale locale = new Locale(1L, 1L, "LINK1", "Insert test", "devschema");
    Locale locale = new Locale(
      1L, 1L, "it_IT", "Italian",
      true, this.currentTimestamp, this.validToDefault,
      "devschema"
    );
    HashMap<String, Object> primaryKeys = new HashMap<String, Object>();
    primaryKeys.put("LANGUAGE_ID", 1L);
    primaryKeys.put("COUNTRY_ID", 1L);
    this.daoLocale.setTable(locale);
    try {
      rowsAffected = this.daoLocale.doInsert(locale, primaryKeys);
    } catch (Exception e) {
      e.printStackTrace();
    }
    assertEquals(1, rowsAffected);
  }

  @Test
  @Order(5)
  void testUpdateTableGenericExpirable() {
    this.daoLocale = (DaoLocale) persistenceLayer.getDaoTableGenericExpirableMap().get("DaoLocale");
    assertTrue(this.daoLocale instanceof DaoTableGenericExpirable);
    Integer rowsAffected = null;
    Locale locale = new Locale(
      1L, 1L, "it_IT", "Italian",
      true, this.currentTimestamp, this.validToDefault,
      "devschema"
    );
    this.daoLocale.setTable(locale);
    try {
      rowsAffected = this.daoLocale.doUpdate(locale);
    } catch (Exception e) {
      e.printStackTrace();
    }
    assertEquals(1, rowsAffected);
  }

  @Test
  @Order(6)
  void testSelectTableGenericExpirable() {
    this.daoLocale = (DaoLocale) persistenceLayer.getDaoTableGenericExpirableMap().get("DaoLocale");
    assertTrue(this.daoLocale instanceof DaoTableGenericExpirable);
    Locale locale = null;
    HashMap<String, Object> primaryKeys = new HashMap<String, Object>();
    primaryKeys.put("LANGUAGE_ID", 1L);
    primaryKeys.put("COUNTRY_ID", 1L);
    try {
      locale = (Locale) this.daoLocale.doSelect(primaryKeys);
    } catch (Exception e) {
      e.printStackTrace();
    }
    assertEquals(1L, locale.getPrimaryKeys().get("LANGUAGE_ID"));
    assertEquals(1L, locale.getPrimaryKeys().get("COUNTRY_ID"));
  }

  @Test
  @Order(7)
  void testManualInsertTableGenericExpirable() {
    this.daoLocale = (DaoLocale) persistenceLayer.getDaoTableGenericExpirableMap().get("DaoLocale");
    assertTrue(this.daoLocale instanceof DaoTableGenericExpirable);
    String insertSql = this.daoLocale.getTable().getSqlInsert();
    this.daoLocale.setSqlCommand(insertSql);
    ArrayList<Object> sqlParameters = new ArrayList<Object>();
    sqlParameters.add(2L);
    sqlParameters.add(2L);
    sqlParameters.add("en_GB");
    sqlParameters.add("British English");
    sqlParameters.add(true);
    sqlParameters.add(this.currentTimestamp);
    sqlParameters.add(this.validToDefault);
    this.daoLocale.setSqlParameters(sqlParameters);
    Integer rowsAffected = 0;
    try {
      rowsAffected = this.daoLocale.doManualDmlOrDdl();
    } catch (Exception e) {
      e.printStackTrace();
    }
    assertEquals(1, rowsAffected);
  }

  @Test
  @Order(8)
  void testManualUpdateTableGenericExpirable() {
    this.daoLocale = (DaoLocale) persistenceLayer.getDaoTableGenericExpirableMap().get("DaoLocale");
    assertTrue(this.daoLocale instanceof DaoTableGenericExpirable);
    String updateSql = this.daoLocale.getTable().getSqlUpdate();
    this.daoLocale.setSqlCommand(updateSql);
    ArrayList<Object> sqlParameters = new ArrayList<Object>();
    sqlParameters.add("en_GB");
    sqlParameters.add("British English");
    sqlParameters.add(true);
    sqlParameters.add(this.currentTimestamp);
    sqlParameters.add(this.validToDefault);
    sqlParameters.add(2L);
    sqlParameters.add(2L);
    this.daoLocale.setSqlParameters(sqlParameters);
    this.daoLocale.setSqlParameters(sqlParameters);
    Integer rowsAffected = 0;
    try {
      rowsAffected = this.daoLocale.doManualDmlOrDdl();
    } catch (Exception e) {
      e.printStackTrace();
    }
    assertEquals(1, rowsAffected);
  }

  @Test
  @Order(9)
  void testManualSelectTableGenericExpirable() {
    this.daoLocale = (DaoLocale) persistenceLayer.getDaoTableGenericExpirableMap().get("DaoLocale");
    assertTrue(this.daoLocale instanceof DaoTableGenericExpirable);
    String selectSql = this.daoLocale.getTable().getSqlSelect();
    this.daoLocale.setSqlCommand(selectSql);
    ArrayList<Object> sqlParameters = new ArrayList<Object>();
    sqlParameters.add(2L);
    sqlParameters.add(2L);
    this.daoLocale.setSqlParameters(sqlParameters);
    ResultSet resultSet = null;
    Long retriviedId = 0L;
    try {
      resultSet = this.daoLocale.doManualSelect();
      resultSet.first();
      retriviedId = resultSet.getLong(1);
    } catch (Exception e) {
      e.printStackTrace();
    }
    assertEquals(2L, retriviedId);
  }

  @Test
  @Order(10)
  void testStopLayer() {
    assertTrue(persistenceLayer.stopLayer());
  }

  @AfterAll
  static void tearDownAfterClass() throws Exception {
    persistenceLayer = null;
  }

}
